package icasue.reflect.handles.map;

import icasue.reflect.exceptions.HandleException;
import icasue.reflect.handles.HandleSupplier;
import icasue.reflect.handles.OFAble;
import icasue.reflect.handles.classes.ClassOF;
import icasue.reflect.handles.exception.ExceptionOF;
import icasue.reflect.handles.object.ObjectOF;

import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2020/12/1 上午11:52
 * @UpdateDate:
 * @Description:
 */
public class MapOF implements OFAble {

    /**
     *  clear_  (map)
     *  size_  (map)
     *  put_    (map,key,val)
     *  putAll_  (map,map)
     *  putIfAbsent_    (map,key,val)
     *      doc: do put if key not existed, return this key's mapping val after process.
     *  get_    (map,key)
     *      doc: get existed value orElse return null.
     *  getOrDefault_    (map,key,defaultVal)
     *      doc: get existed value orElse return defaultValue.
     *  remove_    (map,key)
     *      doc: return value which be removed if exist.
     *
     *  All method check pass.
     */
    public static Consumer<Object> clear_ = (map) -> {
        try {
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,map.getClass()}))
                MapO.clear.bindTo(map).invoke();
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.clear_ occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.ConsumerAry putAll_ = (maps) -> {
        try {
            if(maps.length != 2)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.putAll_ : required 2 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class, maps[0].getClass()})
                    && ClassOF.isAssignableFrom_.test(new Object[]{Map.class, maps[1].getClass()}))
                MapO.putAll.bindTo(maps[0]).invoke(maps[1]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.putAll_ : required params all assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.putAll_ : occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.FunctionAry<Object> put_ = (mapsAndKeyValue) -> {
        try {
            if(mapsAndKeyValue.length != 3)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.put_ : required 3 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class, mapsAndKeyValue[0].getClass()}))
                return MapO.put.bindTo(mapsAndKeyValue[0]).invoke(mapsAndKeyValue[1],mapsAndKeyValue[2]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.put_ : required first params which you given is assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.put_ : occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.FunctionAry<Object> putIfAbsent_ = (mapsAndKeyValue) -> {
        try {
            if(mapsAndKeyValue.length != 3)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.putIfAbsent_ : required 3 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,mapsAndKeyValue[0].getClass()}))
                return MapO.put.bindTo(mapsAndKeyValue[0]).invoke(mapsAndKeyValue[1],mapsAndKeyValue[2]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.putIfAbsent_ : required first params which you given is assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.putIfAbsent_ : occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.FunctionAry<Object> get_ = (mapsAndKey) -> {
        try {
            if(mapsAndKey.length != 2)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.get_ : required 2 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,mapsAndKey[0].getClass()}))
                return MapO.get.bindTo(mapsAndKey[0]).invoke(mapsAndKey[1]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.get_ : required first params which you given is assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.get_ : occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.FunctionAry<Object> getOrDefault_ = (mapsAndKeyDValue) -> {
        try {
            if(mapsAndKeyDValue.length != 3)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.getOrDefault_ : required 3 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,mapsAndKeyDValue[0].getClass()}))
                return MapO.getOrDefault.bindTo(mapsAndKeyDValue[0]).invoke(mapsAndKeyDValue[1],mapsAndKeyDValue[2]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.getOrDefault_ : required first params which you given is assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.getOrDefault_ : occur an error : " , throwable.getMessage());
        }
    };

    public static HandleSupplier.FunctionAry<Object> remove_ = (mapsAndKey) -> {
        try {
            if(mapsAndKey.length != 2)
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.remove_ : required 2 params.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,mapsAndKey[0].getClass()}))
                return MapO.remove.bindTo(mapsAndKey[0]).invoke(mapsAndKey[1]);
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.remove_ : required first params which you given is assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.remove_ : occur an error : " , throwable.getMessage());
        }
    };

    public static Function<Object,Object> size_ = (map) -> {
        try {
            if(ObjectOF.isNull_.test(map))
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.size_ : the param must not be null.");
            if(ClassOF.isAssignableFrom_.test(new Object[]{Map.class,map.getClass()}))
                return MapO.size.bindTo(map).invoke();
            else
                throw ExceptionOF.handleExcInvocation_.apply("MapOF.size_ : the param must be assignable from java.util.Map.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("MapOF.size_ : occur an error : " , throwable.getMessage());
        }
    };


}
